package android.test.until;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import org.apache.http.util.EncodingUtils;
import android.util.Log;
import android.os.SystemProperties;

public class Max3HWVerion
{
    static final String TAG = "MAX3";

    public static String getHWVersion() {
        Max3GPIO gpio0 = new Max3GPIO(Max3GPIO.GPIO_HW_VER_0, Max3GPIO.GPIO_INPUT);
        Max3GPIO gpio1 = new Max3GPIO(Max3GPIO.GPIO_HW_VER_1, Max3GPIO.GPIO_INPUT);
        Max3GPIO gpio2 = new Max3GPIO(Max3GPIO.GPIO_HW_VER_2, Max3GPIO.GPIO_INPUT);
        gpio0.open();
        gpio1.open();
        gpio2.open();
        int bit0  = gpio0.getValue();
        int bit1  = gpio1.getValue();
        int bit2  = gpio2.getValue();
        gpio0.close();
        gpio1.close();
        gpio2.close();
        int value = (bit0 << 0) | (bit1 << 1) | (bit2 << 2);
        if (value != -1) {
            value &= 0x7;
            return String.format("%d.0", value);
        }
        else return "unknow";
    }

    public static String getGPRSVersion() {
        return SystemProperties.get("sys.gprs.version", "unknown");
    }

    public static String getGPSVersion() {
        return execCmdRetOut("gpsexe -version");
    }

    public static String getSerialNumber() {
        int     len  = 512;
        byte [] buf  = new byte[len];
        String  res  = "";
        String  file = "/proc/cpuinfo";
        try {
            FileInputStream fin = new FileInputStream(file);
            len = fin.read(buf);
            fin.close();
            res = EncodingUtils.getString(buf, "UTF-8").substring(len-17, len-1).toUpperCase();
        } catch(Exception e) {
            e.printStackTrace();
        }
        /*
        Log.d(TAG, "read file, name = " + fileName);
        Log.d(TAG, "read file, len  = " + len     );
        Log.d(TAG, "read file, data = " + res     );
        */
        return res;
    }

    public static String getExternelSpeaker() {
        Max3GPIO gpio  = new Max3GPIO(Max3GPIO.GPIO_EXT_SPEAKER_DET, Max3GPIO.GPIO_INPUT);
        int      value = 1;
        gpio.open();
        value = gpio.getValue();
        gpio.close();
        switch (value)
        {
        case 0:
            return "connected";
        case 1:
            return "disconnect";
        default:
            return "unknow";
        }
    }

    public static boolean isGPRSHardwareOK() {
        File ttyMUX1 = new File("/dev/ttyMUX1");
        return ttyMUX1.exists();
    }

    public static boolean isMapApkDataOK() {
        File wikangoxl = new File("/system/app/wikango_xl.apk");
        File wikangoup = new File("/system/app/wikango_up.apk");
        File systemdb1 = new File("/system/database/wikango.sqlite");
        File systemdb2 = new File("/system/database/wikangomap.spatialite");
        File datadb1   = new File("/data/database/wikango.sqlite");
        File datadb2   = new File("/data/database/wikangomap.spatialite");
        File datadb3   = new File("/data/database/osm.spatialite");

        if (  wikangoxl.exists() && wikangoup.exists()
           && systemdb1.exists() && systemdb2.exists()
           && datadb1.exists() && datadb2.exists()
           && datadb3.exists() && datadb3.length() == 1407805440) {
            return true;
        }
        else return false;
    }

    public static void setExtLcdBacklight(int incdec, int lowhigh) {
        Max3GPIO gpio = null;
        switch (incdec)
        {
        case -1:
            gpio = new Max3GPIO(Max3GPIO.GPIO_EXT_LCD_BACKLIGHT_DEC, Max3GPIO.GPIO_OUTPUT);
            break;
        case  1:
            gpio = new Max3GPIO(Max3GPIO.GPIO_EXT_LCD_BACKLIGHT_INC, Max3GPIO.GPIO_OUTPUT);
            break;
        }
        gpio.open();
        gpio.setValue(lowhigh);
    }

    public static void setExtLedOnOff(int value) {
        Max3GPIO gpio = new Max3GPIO(Max3GPIO.GPIO_EXT_MUTE_CTRL, Max3GPIO.GPIO_OUTPUT);
        gpio.open();
        gpio.setValue(value);
    }

    public static boolean runRootCommand(String command) {
        Process     process = null;
        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec("/system/xbin/su");
            os = new DataOutputStream(process.getOutputStream());
            os.writeBytes(command + "\n");
            os.writeBytes("exit\n");
            os.flush();
            process.waitFor();
        } catch (Exception e) {
//          Log.d("*** DEBUG ***", "Unexpected error - Here is what I know: " + e.getMessage());
            return false;
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
//              process.destroy();
            } catch (Exception e) {
                // nothing
            }
        }
        return true;
    }

    public static String execCmdRetOut(String cmd) {
        try {
            Process mProcess = Runtime.getRuntime().exec(cmd);
            try {
                mProcess.waitFor();
            } catch (Exception e) {
                e.printStackTrace();
                return e.getMessage();
            }
            InputStream inputStream = mProcess.getInputStream();
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            String out = dataInputStream.readLine();
            inputStream.close();
            dataInputStream.close();
            return out ;
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }
}

class Max3GPIO {
    final String TAG = "MAX3";
    public static final int GPIO_INPUT  = 0;
    public static final int GPIO_OUTPUT = 1;

    public static final int GPIO_USB_CHARGE_CURRENT_SWITCH = 39;  // GPIO1[7]
    public static final int GPIO_EXT_LCD_BACKLIGHT_INC     = 57;  // GPIO1[25]
    public static final int GPIO_EXT_LCD_BACKLIGHT_DEC     = 56;  // GPIO1[24]
    public static final int GPIO_EXT_SPEAKER_DET           = 5;   // GPIO0[5]
    public static final int GPIO_EXT_MUTE_CTRL             = 100; // GPIO3[4]
    public static final int GPIO_HW_VER_0                  = 36;  // GPIO1[4]
    public static final int GPIO_HW_VER_1                  = 37;  // GPIO1[5]
    public static final int GPIO_HW_VER_2                  = 38;  // GPIO1[6]

    private int gpio_num;
    private int gpio_dir;

    private static final String GPIO_EXPORT_PATH   = "/sys/class/gpio/export";
    private static final String GPIO_UNEXPORT_PATH = "/sys/class/gpio/unexport";
    private static final String GPIO_GPIOXX_PATH   = "/sys/class/gpio/gpio";

    public Max3GPIO(int gpio, int dir) {
        gpio_num = gpio;
        gpio_dir = dir ;
    }

    public void open() {
        String file = null;
        String data = null;

        file = GPIO_EXPORT_PATH;
        data = String.format("%d", gpio_num);
        writeFileData(file, data);

        file = String.format("%s%d/%s", GPIO_GPIOXX_PATH, gpio_num, "direction");
        data = (gpio_dir == GPIO_OUTPUT) ? "out" : "in";
        writeFileData(file, data);
    }

    public void close() {
        String file = null;
        String data = null;
        file = GPIO_UNEXPORT_PATH;
        data = String.format("%d", gpio_num);
        writeFileData(file, data);
    }

    public int getValue() {
        String file = null;
        String data = null;
        file = String.format("%s%d/%s", GPIO_GPIOXX_PATH, gpio_num, "value");
        data = readFileData(file);
        if      (data.equals("0")) return 0;
        else if (data.equals("1")) return 1;
        else return -1;
    }

    public void setValue(int value) {
        String file = null;
        String data = null;
        file = String.format("%s%d/%s", GPIO_GPIOXX_PATH, gpio_num, "value");
        data = String.format("%d", value);
        writeFileData(file, data);
    }

    public int getDirection() {
        String file = null;
        String data = null;
        file = String.format("%s%d/%s", GPIO_GPIOXX_PATH, gpio_num, "direction");
        data = readFileData(file);
        if      (data.equals("o")) return GPIO_OUTPUT;
        else if (data.equals("i")) return GPIO_INPUT;
        else return -1;
    }

    public void setDirection(int dir) {
        String file = null;
        String data = null;
        file = String.format("%s%d/%s", GPIO_GPIOXX_PATH, gpio_num, "direction");
        data = (dir == GPIO_OUTPUT) ? "out" : "in";
        writeFileData(file, data);
    }

    private void writeFileData(String fileName, String data) {
//      Log.d(TAG, "write file, name = " + fileName);
//      Log.d(TAG, "write file, data = " + data    );
        try {
            File f = new File(fileName);
            if (!f.exists()) {
                return;
            }
            FileOutputStream fout = new FileOutputStream(fileName);
            byte [] bytes = data.getBytes();
            fout.write(bytes);
            fout.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private String readFileData(String fileName) {
        String res = "";
        try {
            FileInputStream fin = new FileInputStream(fileName);
//          int length = fin.available();
            int length = 1;
            byte [] buffer = new byte[length];
            fin.read(buffer);
            res = EncodingUtils.getString(buffer, "UTF-8");
            fin.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
//      Log.d(TAG, "read file, name = " + fileName);
//      Log.d(TAG, "read file, data = " + res     );
        return res;
    }
}
